热门标签 | HotTags
当前位置:  开发笔记 > 后端 > 正文

主存|篇文章_存储优化查询分离

篇首语:本文由编程笔记#小编为大家整理,主要介绍了存储优化--查询分离相关的知识,希望对你有一定的参考价值。 上一篇文章中我们讲解了利用数据库分区与冷热分离的方式来优化

篇首语:本文由编程笔记#小编为大家整理,主要介绍了存储优化--查询分离相关的知识,希望对你有一定的参考价值。



上一篇文章中我们讲解了利用数据库分区与冷热分离的方式来优化存储,虽然解决了查询速度慢的问题,但是在海量数据情况下依然会出现查询缓慢问题,并且部分系统中的冷热数据也是需要频繁或同时查询的。那么,这篇文章中我将带领大家来学习一下如何在设计系统架构时解决海量的数据存储与查询。


一、案例

我们有一个自动化舆情系统,简要的工作流程是这样的:每天数据采集服务会从公共社交媒体上采集数据并存入数据库,识别服务读取数据库中存储的数据按照一定的规则进行分析识别,并将分析识别的结果存入库中,客户端实时读取数据库的分析识别结果,将信息展示出来,而且该系统还要支持舆情追溯功能(例如某人在某公共社交平台发布了不良言论,可以通过该系统查找他以前发布的所有言论以及所有言论的识别结果)。
根据上面对舆情系统的简要描述我们可知,该系统需要采集大量的数据来进行分析,并且需要对历史数据进行查询。因此该系统具备如下两个特征:



  1. 海量数据;

  2. 冷热数据同时查询。

那么根据这两个特征,我们就不能使用上一篇文章中所说的分区或冷热分离的方式来设计数据存储架构了。就目前来看比较适合的就是查询分离方案(目前指的是在这篇文章中,下一篇文章针对舆情系统还有更好的数据存储解决方案)。


二、简介


2.1 概念

每次向数据库中更新数据的同时,将数据也保存到其他存储系统中(其他存储系统可以是),当用户查询数据的时候直接从其他从出系统中查询出即可。这个更新的数据库被称为主存储,用来查询的数据库被称为查询存储。基本架构图如下:


2.2 适用场景

一般来说如果遇到如下问题就可以使用查询分离:



  1. 数据量大,单表数据达到千万;

  2. 查询速度慢,即使加了索引也是很慢;

  3. 存在复杂的表关联查询;

  4. 所有数据都有可能被修改和查询。


三、实现

查询分离的实现思一般分三个步骤:



  1. 如何触发;

  2. 如何实现

  3. 查询存储如何存储。

下面我们就来一一讲解一下。


3.1 如何触发

常见的查询分离触发方式有三种:



  1. 在向主存储更新数据后马上向查询存储更新同样的数据,并在查询存储数据更新完成后向用户返回结果。这种触发方式虽然保证了查询存储数据的实时性和一致性,并且业务逻辑也可控,但是对代码的侵入较大,只要是涉及更新主存储的代码,都要加入向查询存储更新数据的代码。而且这种方式还会减缓写操作的响应时间,因为我们要等待查询存储的数据跟新完成后才能返回响应结果。

  2. 在向主存储更新数据后异步更新查询存储,不等待查询存储数据更新完成,就向用户返回结果。这种方式不影响主流程,但是如果在查询存储更新前,用户进行了相关查询,就会返回过时的数据,而且这种方式对代码同样有侵入性。

  3. 监控主存储日志,如果发生变更,就去更新查询存储。这种方式不影响主流程,对业务代码零侵入,但是在查询存储更新前,用户可能会查到过时的数据,并且这种方式的架构比前两种方式复杂。

下表列出了这三种方式适合的场景:























触发方式适合场景
方式一业务代码简单,而且对写操作响应速度要求不高
方式二业务代码相对复杂,对写操作响应速度有要求
方式三业务代码很复杂,并且代码改动成本高

针对上面三种触发方式的简单讲解和适合场景的描述可知,我们的舆情系统适用于方式二。


3.2 如何实现

我们已经在上一小节中确定使用第二种触发方式来设计我们的数据存储架构了。实现它的思路可以简述为:单独启动一个线程来对查询存储进行更新。但是,这种方式在实现时要考虑如下三个情况:



  1. 当出现大量写入操作时,更新查询存储的线程会很多,就会给舆情系统、查询存储、甚至服务器带来巨大的压力,那么这个时候我们就需要控制跟新查询存储的线程数量了;

  2. 如果在更新查询存储的过程中出现了更新失败的情况,我们应该引入重试机制,那么我们该怎么标识需要重试的数据;

  3. 多线程并发更新查询存储时该怎么处理?

针对上述三种情况,我们可以使用 MQ来解决,思路也很简单:当向主存储更新数据时,都要向MQ发出一个通知,MQ在收到通知后启动一个线程来更新查询存储。
当然在使用 MQ 的时候也会遇到各种问题,最常见的问题就是 MQ 挂掉了。当 MQ 挂掉后会出现如下两种情况:



  1. 主存储跟新完后向MQ发送通知,但是MQ无法收到这个通知,因此数据也就不会更新到查询库里,那么就出现了数据丢失的问题;

  2. MQ 消费者收到消息去更新查询存储后,告诉MQ消费完成,但是MQ这时挂了,已经收不到这个反馈了,但是在MQ重新启动后,这条消息又被投递了,这时就出现了重复投递的问题。

前述的这两种情况我们可以在主存储中增加一个 需要更新到查询存储 字段,每次在向主存储更新数据时就将这个字段设置为 true,扎样在向MQ发消息时只用发送一个简单的更新消息即可,不需要向MQ发送包含数据ID的消息。查询存储更新服务在获取到这个消息后,首先在主存储中查询 ***需要更新到查询存储***字段为true的数据,然后将这些数据批量更新到查询存储中,更新完毕后再将这些数据的**需要更新到查询存储字段改为false即可。
我们也可以利用MQ来实现
削峰
,当更新的请求太多时通过MQ来控制执行同步查询库的线程数。
数据更新到查询存储失败问题我们可以引入重试机制,并且只有在更新成功后才去修改***需要更新到查询存储***字段的值。当然,并不是每次重试机制都能将数据更新成功,因此我们可以设定一个重试次数阈值,当数据重试次数达到这个阈值时就需要及时通知相关人员进行人工干预了。

关于并发问题的解决方法可以参考上一篇文章。
这一小节还剩最后一个问题,时序性问题。例如小明先将A数据更新为123,小红后将A数据更新为321,但是更新查询存储时,小红的更新线程却先于小明的更新线程启动,这时就出现了小明的旧数据覆盖了小红的新数据。解决这个问题也很简单,在主存储中增加 最后更新时间 字段,线程更新完查询存储后,检查当前数据的***最后更新时间*** 字段的值是否和线程刚启动时是一样的,并且***需要更新到查询存储***字段为false,如果满足条件就将***需要更新到查询存储***字段改成true,在做一次更新查询存储活动。


3.3 查询存储如何存储

一般来说比较常见的存储方案是使用 Elasticsearch、MongoDB或Redis,这三种方案都时候复杂查询。但是,具体存储方案的选型应该根据开发组技术情况和项目情况来走。


四、总结

这一篇文章主要讲了查询分离的知识以及如何设计数据存储架构,下一篇我将优化本篇案例的解决方案。


推荐阅读
  • 关于我们EMQ是一家全球领先的开源物联网基础设施软件供应商,服务新产业周期的IoT&5G、边缘计算与云计算市场,交付全球领先的开源物联网消息服务器和流处理数据 ... [详细]
  • Linux如何安装Mongodb的详细步骤和注意事项
    本文介绍了Linux如何安装Mongodb的详细步骤和注意事项,同时介绍了Mongodb的特点和优势。Mongodb是一个开源的数据库,适用于各种规模的企业和各类应用程序。它具有灵活的数据模式和高性能的数据读写操作,能够提高企业的敏捷性和可扩展性。文章还提供了Mongodb的下载安装包地址。 ... [详细]
  • CentOS 7部署KVM虚拟化环境之一架构介绍
    本文介绍了CentOS 7部署KVM虚拟化环境的架构,详细解释了虚拟化技术的概念和原理,包括全虚拟化和半虚拟化。同时介绍了虚拟机的概念和虚拟化软件的作用。 ... [详细]
  • 一句话解决高并发的核心原则
    本文介绍了解决高并发的核心原则,即将用户访问请求尽量往前推,避免访问CDN、静态服务器、动态服务器、数据库和存储,从而实现高性能、高并发、高可扩展的网站架构。同时提到了Google的成功案例,以及适用于千万级别PV站和亿级PV网站的架构层次。 ... [详细]
  • 深入理解Java虚拟机的并发编程与性能优化
    本文主要介绍了Java内存模型与线程的相关概念,探讨了并发编程在服务端应用中的重要性。同时,介绍了Java语言和虚拟机提供的工具,帮助开发人员处理并发方面的问题,提高程序的并发能力和性能优化。文章指出,充分利用计算机处理器的能力和协调线程之间的并发操作是提高服务端程序性能的关键。 ... [详细]
  • 讨伐Java多线程与高并发——MQ篇
    本文是学习Java多线程与高并发知识时做的笔记。这部分内容比较多,按照内容分为5个部分:多线程基础篇JUC篇同步容器和并发容器篇线程池篇MQ篇本篇 ... [详细]
  • celery 爬虫使用
    简介celery是一个基于分布式消息传输的异步任务队列,它专注于实时处理,同时也支持任务调度。它由三部分组成,消息中间件, ... [详细]
  • 数据库基本介绍
    1、数据库基本知识概念:数据库:database(DB),是一种存储数据的仓库数据库是根据数据结构组织、存储和 ... [详细]
  • 基于PgpoolII的PostgreSQL集群安装与配置教程
    本文介绍了基于PgpoolII的PostgreSQL集群的安装与配置教程。Pgpool-II是一个位于PostgreSQL服务器和PostgreSQL数据库客户端之间的中间件,提供了连接池、复制、负载均衡、缓存、看门狗、限制链接等功能,可以用于搭建高可用的PostgreSQL集群。文章详细介绍了通过yum安装Pgpool-II的步骤,并提供了相关的官方参考地址。 ... [详细]
  • Android中高级面试必知必会,积累总结
    本文介绍了Android中高级面试的必知必会内容,并总结了相关经验。文章指出,如今的Android市场对开发人员的要求更高,需要更专业的人才。同时,文章还给出了针对Android岗位的职责和要求,并提供了简历突出的建议。 ... [详细]
  • 本文介绍了如何使用php限制数据库插入的条数并显示每次插入数据库之间的数据数目,以及避免重复提交的方法。同时还介绍了如何限制某一个数据库用户的并发连接数,以及设置数据库的连接数和连接超时时间的方法。最后提供了一些关于浏览器在线用户数和数据库连接数量比例的参考值。 ... [详细]
  • 本文介绍了C#中数据集DataSet对象的使用及相关方法详解,包括DataSet对象的概述、与数据关系对象的互联、Rows集合和Columns集合的组成,以及DataSet对象常用的方法之一——Merge方法的使用。通过本文的阅读,读者可以了解到DataSet对象在C#中的重要性和使用方法。 ... [详细]
  • 0x00端口渗透端口扫描端口的指纹信息(版本信息)端口所对应运行的服务常见的默认端口号.尝试弱口令端口爆破hydra端口弱口令NTScanHs ... [详细]
  • 一份来自清华的数据分析笔记,请查收!
    之前发过很多数据分析的文章,收到不少好评,但也有一些困惑:入门数据分析该学哪些知识点?该看哪些书?是从Pyth ... [详细]
  • 前面刚有AWS开战MongoDB,双方“隔空互呛”,这厢又曝出2亿+简历信息泄露——MongoDB的这场开年似乎“充实”得过分了些。长期以来,作为“最受欢迎的NoSQL数据库”,M ... [详细]
author-avatar
手机用户2502875921
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有